package com.histone.lib_download.downloader;

import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import android.widget.RemoteViews;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;


import com.histone.lib_download.DownloadFactory;
import com.histone.lib_download.R;
import com.histone.lib_download.contract.DownloadTakeNotes;
import com.histone.lib_download.contract.IDownloadProgress;
import com.histone.lib_download.localbroadcast.LocalBroadcastHolder;

import java.io.File;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;

/**
 * @author robin
 * @version v1.0 [2020/6/10]
 * 后台服务 （所属线程-UI 主线程）
 */
public class DownloadService extends Service {

    //开始下载标识
    public static final String DOWNLOAD_START = "DOWNLOAD_START";
    //暂停下载标识
    public static final String DOWNLOAD_STOP = "DOWNLOAD_STOP";
    //取消下载标识
    public static final String DOWNLOAD_CANCEL = "DOWNLOAD_CANCEL";
    //传参标识
    public static final String KEY_FILE_INFO = "key_file_info";
    public static final String KEY_FILE_INFO_LIST = "key_file_info_list";
    //检查剩余空间
    public static final String KEY_CHECK_SPACE = "key_check_space";
    //下载数量
    public static final String KEY_FILE_COUNT = "key_file_count";

    private boolean downFlag = false;
    //是否开启检查 内存空间
    private boolean needCheckFreeSpace = true;

    private ArrayList<FileInfo> listFile;

    private Downloader downloader = null;

    private RemoteViews remoteViews;
    private Notification build;
    private FileInfo fileInfo;

    @Override
    public void onCreate() {
        super.onCreate();
        Intent intent = new Intent(this, DownloadService.class);
        intent.setAction(DownloadService.DOWNLOAD_STOP);
        remoteViews = new RemoteViews(getPackageName(), R.layout.layout_download_progress);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (intent == null) {
            Toast.makeText(this, "error", Toast.LENGTH_SHORT).show();
        } else {
            //开始下载命令
            if (DOWNLOAD_START.equals(intent.getAction())) {
                downFlag = true;
                fileInfo = (FileInfo) intent.getSerializableExtra(KEY_FILE_INFO);
                needCheckFreeSpace = intent.getBooleanExtra(KEY_CHECK_SPACE, true);
                if (fileInfo != null) {
                    startInitThread(fileInfo);
                    showNotification(remoteViews);
                }
            } else if (DOWNLOAD_STOP.equals(intent.getAction())) {
                downFlag = false;
                FileInfo fileInfo = (FileInfo) intent.getSerializableExtra(KEY_FILE_INFO);
                if (downloader != null) {
                    downloader.isPause = true;
//                    remoteViews.setTextViewText(R.id.txt_start, "开始");
                    onNotificationNotify();
                }
            }
        }
        return super.onStartCommand(intent, flags, startId);
    }

    //启动初始化线程
    private void startInitThread(FileInfo info) {
        if (!downFlag) return;
        InitRunnable initRunnable = new InitRunnable(info);
        DownloadFactory.runOnAsync(initRunnable);
    }

    /**
     * 下载任务
     */
    private void startDownload(FileInfo info) {
        downloader = null;
        downloader = new Downloader(this, info);
        downloader.download(new IDownloadProgress() {
            long time = System.currentTimeMillis();

            //进度监听
            @Override
            public void onAsyncProgress(long finished, long length) {
                //每1秒通知一次进度 todo 根据实际情况调整
                if (System.currentTimeMillis() - time > 1000) {
                    time = System.currentTimeMillis();
                    Message message = new Message();
                    message.obj = (int) ((finished * 100) / length);
                    message.what = code_progress;
                    mHandler.sendMessage(message);
                }
                if (finished == length) {
                    Message message = new Message();
                    message.obj = 100;
                    message.what = code_progress;
                    mHandler.sendMessage(message);
                }

            }

            @Override
            public void onDownloadSuccess(FileInfo fileInfo) {
                Message message = new Message();
                message.obj = fileInfo;
                message.what = code_download_success;
                mHandler.sendMessage(message);
            }

            @Override
            public void onDownloadError(Throwable throwable) {
                remoteViews.setTextViewText(R.id.txt_start, "重试");
                mHandler.sendEmptyMessage(code_download_error);
            }
        });
        remoteViews.setTextViewText(R.id.txt_name, "文件：" + info.fileName);
        remoteViews.setProgressBar(R.id.progressBar, 100, 0, false);
        remoteViews.setTextViewText(R.id.txt_all_count, 1 + "/" + 1);
        remoteViews.setTextViewText(R.id.txt_start, "正在下载");
        onNotificationNotify();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    private NotificationManager mNotificationManager;

    private void showNotification(RemoteViews remoteViews) {
        Notification.Builder builder = null;
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
            builder = new Notification.Builder(this);
        } else {
            NotificationChannel notificationChannel = new
                    NotificationChannel(String.valueOf(getPackageName() + "_id"), String.valueOf(getPackageName() + "_name"), NotificationManager.IMPORTANCE_DEFAULT); //如果这里用IMPORTANCE_NOENE就需要在系统的设置里面开启渠道， //通知才能正常弹出
            getNotificationManager().createNotificationChannel(notificationChannel);
            builder = new Notification.Builder(this, String.valueOf(getPackageName() + "_id"));
        }
        builder.setContentTitle("下载任务");
        builder.setContentText("正在下载文件");
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            builder.setCustomBigContentView(remoteViews);
        } else {
            builder.setContent(remoteViews);
        }
        builder.setWhen(System.currentTimeMillis());
        builder.setSmallIcon(R.drawable.baseline_cloud_download_24);
        builder.setAutoCancel(true);
//        builder.setOngoing(true);
        build = builder.build();
        onNotificationNotify();
    }

    private NotificationManager getNotificationManager() {
        if (mNotificationManager == null) {
            mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        }
        return mNotificationManager;
    }

    /**
     * 更新通知
     */
    private void onNotificationNotify() {
        if (build == null) return;
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
            getNotificationManager().notify(10, build);
        } else {
            startForeground(0x10, build);
        }
    }

    private void cancelNotification() {
        if (build == null) return;
        getNotificationManager().cancelAll();
    }

    //初始化 （计算文件大小）
    class InitRunnable implements Runnable {
        private final FileInfo fileInfo;

        public InitRunnable(FileInfo fileInfo) {
            this.fileInfo = fileInfo;
        }

        @Override
        public void run() {
            HttpURLConnection huc = null;
            try {
                URL url = new URL(fileInfo.downloadUrl);
                huc = (HttpURLConnection) url.openConnection();
                huc.setConnectTimeout(5000);
                huc.setRequestMethod("GET");
                //获取文件length
                int length = -1;
                if (huc.getResponseCode() == HttpURLConnection.HTTP_OK) {
                    length = huc.getContentLength();
                    if (TextUtils.isEmpty(fileInfo.fileName)) {
                        fileInfo.fileName = DownloadFactory.checkFileName(huc.getHeaderField("Content-Disposition"));
                    }
                }
                if (length < 0) {
                    fileInfo.fileLength = length;
                    if (TextUtils.isEmpty(fileInfo.fileName)) {
                        fileInfo.fileName = DownloadFactory.urlName(fileInfo.downloadUrl);
                    }
                    Message message = new Message();
                    message.what = code_init_error;
                    message.obj = fileInfo;
                    mHandler.sendMessage(message);
                    return;
                }
                fileInfo.fileLength = length;
                if (TextUtils.isEmpty(fileInfo.fileName)) {
                    fileInfo.fileName = DownloadFactory.urlName(fileInfo.downloadUrl);
                }
//                fileInfo.localFilePath = DownloadFactory.getDefaultFile() + "/" + fileInfo.fileName;
                Message message = new Message();
                message.what = code_init_success;
                message.obj = fileInfo;
                mHandler.sendMessage(message);

            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (huc != null)
                    huc.disconnect();
            }
        }
    }

    public static final int code_init_error = 0x01;
    public static final int code_init_success = 0x02;
    public static final int code_download_error = 0x03;
    //下载成功
    public static final int code_download_success = 0x04;
    //下载进度
    public static final int code_progress = 0x05;
    //磁盘空间不足
    public static final int code_download_error_space = 0x06;
    //关闭服务
    public static final int code_server_stop = 0x07;
    @SuppressLint("HandlerLeak")
    private final Handler mHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(@NonNull Message msg) {
            switch (msg.what) {
                case code_init_error:
                    FileInfo infoError = (FileInfo) msg.obj;
                    //广播通知
                    Intent intentError = new Intent(LocalBroadcastHolder.LOCAL_BROADCAST_ACTION);
                    intentError.putExtra(LocalBroadcastHolder.BROADCAST_CODE, LocalBroadcastHolder.CODE_ERROR);
                    intentError.putExtra(LocalBroadcastHolder.BROADCAST_FILE_INFO, infoError);
                    LocalBroadcastHolder.getInstance().sendBroadcast(DownloadService.this, intentError);
                    remoteViews.setTextViewText(R.id.txt_start, "下载数据异常");
                    onNotificationNotify();
                    //结束服务
                    mHandler.sendEmptyMessageDelayed(code_server_stop, 2000);
                    break;
                case code_init_success:
                    FileInfo info = (FileInfo) msg.obj;
                    if (needCheckFreeSpace) {
                        DownloadFactory.runOnAsync(new ThreadCheckSpace(DownloadService.this, info.finishLength));
                    } else {
                        startDownload(info);
                    }
                    break;
                case code_download_success:
                    //广播通知
                    FileInfo infoDownloaded = (FileInfo) msg.obj;
                    Intent intent = new Intent(LocalBroadcastHolder.LOCAL_BROADCAST_ACTION);
                    intent.putExtra(LocalBroadcastHolder.BROADCAST_CODE, LocalBroadcastHolder.CODE_OK);
                    intent.putExtra(LocalBroadcastHolder.BROADCAST_FILE_INFO, infoDownloaded);
                    LocalBroadcastHolder.getInstance().sendBroadcast(DownloadService.this, intent);
                    DownloadTakeNotes.getInstance().clean();
                    //启动安装
                    if (infoDownloaded != null) {
                        File fApk = new File(infoDownloaded.localFilePath, infoDownloaded.fileName);
                        Log.i("下载完成，启动安装", fApk.toString());
                        if (fApk.isFile())
                            DownloadFactory.initApk(DownloadService.this, fApk);
                    }
                    //结束服务
                    mHandler.sendEmptyMessageDelayed(code_server_stop, 2000);
                    cancelNotification();
                    break;
                case code_progress:
                    int pos = (int) msg.obj;
                    remoteViews.setProgressBar(R.id.progressBar, 100, (int) pos, false);
                    remoteViews.setTextViewText(R.id.txt_jd, pos + "%");
                    //更新通知栏
                    onNotificationNotify();
                    break;
                case code_download_error_space:
                    Intent intentSpace = new Intent(LocalBroadcastHolder.LOCAL_BROADCAST_ACTION);
                    intentSpace.putExtra(LocalBroadcastHolder.BROADCAST_CODE, LocalBroadcastHolder.CODE_ERROR_NO_SPACE);
                    LocalBroadcastHolder.getInstance().sendBroadcast(DownloadService.this, intentSpace);
                    remoteViews.setTextViewText(R.id.txt_start, "磁盘空间不足");
                    //更新通知栏
                    onNotificationNotify();
                    //结束服务
                    mHandler.sendEmptyMessageDelayed(code_server_stop, 2000);
                    break;
                case code_download_error:
                    Intent intentDownloadError = new Intent(LocalBroadcastHolder.LOCAL_BROADCAST_ACTION);
                    intentDownloadError.putExtra(LocalBroadcastHolder.BROADCAST_CODE, LocalBroadcastHolder.CODE_ERROR);
                    LocalBroadcastHolder.getInstance().sendBroadcast(DownloadService.this, intentDownloadError);
                    remoteViews.setTextViewText(R.id.txt_start, "下载异常");
                    //更新通知栏
                    onNotificationNotify();
                    //结束服务
                    mHandler.sendEmptyMessageDelayed(code_server_stop, 2000);
                    break;

                case code_server_stop:
                    stopSelf();
                default:
                    break;
            }
            super.handleMessage(msg);
        }
    };

    //检测sd卡空间
    class ThreadCheckSpace implements Runnable {
        Context context;
        long needSpace;

        public ThreadCheckSpace(Context context, long needSpace) {
            this.context = context;
            this.needSpace = needSpace;
        }

        @Override
        public void run() {
            if (DownloadFactory.getFreeSpaceLength(context) <= needSpace) {
                mHandler.sendEmptyMessage(code_download_error_space);
            } else {
                startDownload(fileInfo);
                Log.i("Thread-check", "downloading...");
            }
        }
    }
}
